////////////////////////////////////////////////////////////////////////////////
/*!	\file		Node.hpp
**	\brief		Defines the node class used by all Decision Trees.
**	\author		Nate Cleveland
**	\date		11/14/2002 1:53:08 PM
**	\par		DESCRIPTION:
**				 - The () operator is used to evoke Dtrees. 
**				 - Deleteing the root of the tree will cause it to automatically free its 
**				 children. 
**				 - When calling SetLeft(...) or SetRight(...) the member must be null or 
**				 else these methods will cause an assertion failure. This is done to 
**				 prevent memory leaks.
**
**	\par		REMARKS:
**					
*/
////////////////////////////////////////////////////////////////////////////////
#include <assert.h>
#pragma once


namespace DTree
{
	//!Predicate type used by DTree::Node.
	typedef char NodePredicate;

	//!The only types supported by NodePredicate.
	const NodePredicate LESS_EQUAL = '<';
	const NodePredicate EQUAL_TO = '=';

	template <class Node_Type>
	class TreeFileIO;
	

	////////////////////////////////////////////////////////////////////////////////
	/*!	\class		Node
	**	\brief		Defines the node/leaf/branch logic for all Dtrees.
	**	\author		Nate Cleveland
	**	\date		11/18/2002 4:46:18 PM
	**	\warning	none
	*/
	////////////////////////////////////////////////////////////////////////////////
	template<class Case_type, class Class_type, class CaseExpander_func>
	class Node
	{
		
	protected:		
		//If this node holds any logic....
		unsigned long	m_caseIndex;	//!< Index to the particular case we need to test.
		float			m_caseValue;	//!< Value we need to test the particular case against.

		NodePredicate	m_type;			//!< Predicate to evaulate this node with.
		
		//if this node is just a result....
		Class_type		m_class;		//!< if either left or right are both null then return this value.
		
		
	public:		
		Node*			m_left;			//!< true/Yes result.			THIS NEEDS TO BE PROTECTED.
		Node*			m_right;		//!< false/No result.			THIS NEEDS TO BE PROTECTED.
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Recursively evaluates this tree.
		**	\param		cases		Each element of this vector is a specific case.
		**	\return		Returns to the caller the value of the end leaf.
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:37:22 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		Class_type operator () (std::vector<Case_type>& cases);
		

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Defualt ctor. sets all members to NULL/0.
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:34:58 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		Node() throw()
			:m_left(NULL), m_right(NULL), m_class(0), m_caseValue(0), 
			 m_type(0), m_caseIndex(0){}
		
		//use this node if you want this to be a leaf
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Ctor to use if you wish to create a leaf.
		**	\param		result		Result you wish this	
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:33:47 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		Node(const Class_type& result) throw()
			:m_left(NULL), m_right(NULL), m_class(result), m_caseValue(0), 
			 m_type(0), m_caseIndex(0){}
		
		//Use this node if you wish to specify this as non-answer node.
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Ctor to use if you wish to create a branch.
		**	\param		value		Value for this node.
		**	\param		index		Index that this node compairs itself with.
		**	\param		left		Pntr to the left child.
		**	\param		righ		pntr to the right child.
		**
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:32:16 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		Node(Case_type	caseValue, unsigned long index, Node* left = NULL, Node* right=NULL)
			 throw(): m_left(left), m_right(right), m_class(0), m_type(0), 
			 m_caseValue(caseValue), m_caseIndex(index){}
		

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Node dtor
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Calls delete on each child.	
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:31:39 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		~Node() throw()
		{
			if(m_left ) delete m_left;
			if(m_right) delete m_right;
		}

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Provides the caller with a mechanism for creating deep copies.
		**	\param		oldNode			Reference to the node we're copying from
		**	\param		newNode			Ref
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/22/2002 3:48:21 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		static void DeepCopy(Node& oldNode, Node& newNode)
		{
			//copy everything over.
			newNode = oldNode;

			//create new chilren
			if(oldNode.m_left)
			{
				newNode.m_left = new Node;
				DeepCopy(*oldNode.m_left, *newNode.m_left);
			}

			if(oldNode.m_right)
			{
				newNode.m_right = new Node;
				DeepCopy(*oldNode.m_right, *newNode.m_right);
			}
		}
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		CalcPred takes the left-hand and right-hand and computes them
		**				 based on the given predicate.
		**
		**	\param		pred	Predicate to evaluate the values with.
		**	\param		lhs		Left-Hand value to evaluate.
		**	\param		rhs		Right-Hand value to evalute.
		**
		**	\return		Returns the boolean result of the predicate compairson.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				Calculates the last two values based on the predicate passed to it.	
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:26:13 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		static bool CalcPred(NodePredicate pred, float lhs, float rhs);

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Compairs two values based on this node's predicate.
		**	\param		lhs		Left-Hand value to evaluate.
		**	\param		rhs		Right-Hand value to evalute.	
		**	\return		Returns the boolean result of the predicate compairson.
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:29:42 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		bool		CalcPred(float lhs, float rhs){return CalcPred(this->m_type, lhs, rhs);}

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Compairs the given value in terms of this node's predicate and
		**				 node's values.
		**
		**	\param		pred	Predicate to evaluate the values with.
		**	\param		lhs		Left-Hand value to evaluate.
		**	\param		rhs		Right-Hand value to evalute.
		**
		**	\return		Returns the boolean result of the predicate compairson.	
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/18/2002 4:30:31 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		bool		CalcPred(float lhs){return CalcPred(this->m_type, lhs, m_caseValue);}
		
		
		
		//Standard accessor methods.
		void SetLeft		(Node* left)						{assert(NULL == m_left);m_left = left;}
		void SetRight		(Node* right)						{assert(NULL == m_right);m_right = right;}
		void SetClass		(const Class_type& newClass) throw(){m_class = newClass;}
		void SetCaseIndex	(unsigned long caseIndex)	 throw(){m_caseIndex = caseIndex;}
		void SetCaseValue	(float caseValue)			 throw(){m_caseValue = caseValue;}	
		void SetPredType	(NodePredicate ty)			 throw(){m_type = ty;}
		
		
		const Node*		GetLeft(void)      const throw()	{return m_left;}
		const Node*		GetRight(void)     const throw()	{return m_right;}
		Node*			GetLeft(void)            throw()	{return m_left;}
		Node*			GetRight(void)           throw()	{return m_right;}
		unsigned long	GetClass(void)	   const throw()	{return m_class;}
		unsigned long	GetCaseIndex(void) const throw()	{return m_caseIndex;}
		float			GetCaseValue(void) const throw()	{return m_caseValue;}	
		NodePredicate	GetPredType(void)  const throw()	{return m_type;}
	};//end Node

	/*!
	**	Since Visual C++ 6.0 does not support the export keyword we must use a hack around.
	**	 The hack is to #include the .cpp file. Ugly and evil, but it is the only option if
	**	 we wish to use a generic templitized method. If this file is ever included into a 
	**	 non-Visual C++ (or borland) workspace this hack should be removed and the 
	**	 keyword "export" added before each instance of the world "template" in 
	**	 node.cpp.
	*/
#	include "node.cpp"
}